<?php
namespace App\Services\WxMaterial;

use App\Models\WxMaterial;
use App\Services\EasyWechat;
use App\Services\SysFileService;
use App\Services\WxErrorService;
use EasyWeChat\Kernel\Messages\Video;
/**
 * 视频素材业务逻辑
 * @package App\Services\WxMaterial
 */
class WxMaterialVideo implements WxMaterialInterface
{
    /**
     * 保存素材数据
     * @param $data
     */
    public function save($data)
    {
        \DB::beginTransaction();
        try {
            $materialId = $data['material_id'] ?? 0;
            if ($materialId){
                $materialModel = WxMaterial::findOrFail($materialId);
            }else{
                $materialModel = new WxMaterial;
            }
            $materialModel->cat_id = $data['cat_id'] ?? 0;
            $materialModel->type = 'video';
            $materialModel->title = $data['title'] ?? '';
            $materialModel->description = $data['description'] ?? '';
            $materialModel->view_url = $data['view_url'] ?? '';
            //素材本地文件
            $localFileInfo = (new SysFileService())->getLocalFileInfoByRemoteUrl($data['view_url']);
            $materialModel->file_id = $localFileInfo['file_id'] ?? 0;

            $materialModel->is_forever = $data['is_forever'] ?? 0;
            $materialModel->preview_data = [
                'title' => $materialModel->title,
                'view_url' => $materialModel->view_url,
            ];
            $materialModel->save();
            \DB::commit();
        } catch (\Exception $e) {
            \DB::rollBack();
            throw new \Exception($e->getMessage());
        }
        //永久素材则异步获取mediaId
        if (empty($data['material_id'])) {
            \App\Jobs\WxMaterialVideoUpload::dispatch($materialModel->material_id)->onQueue('low');
        }
        return true;
    }

    /**
     * 删除素材
     * @param $materialId
     */
    public function del($materialId)
    {
        $findMaterial = WxMaterial::findOrFail($materialId);
        \DB::beginTransaction();
        try {
            //永久素材需要调用接口删除
            if (!empty($findMaterial->media_id)) {
                $app = EasyWechat::officialAccount();
                if ($findMaterial->is_forever){
                    $apiRs = $app->material->delete($findMaterial->media_id);
                    WxErrorService::checkApiResponse($apiRs);
                }
            }
            $findMaterial->media_id = '';
            $findMaterial->expire_time = null;
            $findMaterial->save();
            $findMaterial->delete();
            \DB::commit();
        } catch (\Exception $e) {
            \DB::rollBack();
            throw new \Exception($e->getMessage());
        }
        return true;
    }

    /**
     * 获取被动回复数据
     * @param $materialId
     */
    public function getPassiveReplyData($materialId)
    {
        $mediaId = $this->getMediaId($materialId);
        if ($mediaId){
            $findMaterial = WxMaterial::find($materialId);

            return new Video($mediaId, [
                'title' => $findMaterial->title ?? '',
                'description' => $findMaterial->description ?? '',
                'thumb_media_id' => $findMaterial->thumb_media_id ?? '',
            ]);
        }else{
            return '';
        }
    }

    /**
     * 获取微信mediaId（临时素材和永久素材处理方式不一样）
     * @param $materialId 素材主键ID
     * @param $reUpload 是否重新上传
     * @return string 素材media_id
     */
    public function getMediaId($materialId, $reUpload = false)
    {
        $findMaterial = WxMaterial::findOrFail($materialId);
        $findMaterial->push_result = '';
        //上传到微信素材
        $app = \App\Services\EasyWechat::officialAccount();
        //临时素材更新mediaId
        if ($findMaterial->is_forever == 0 && (empty($findMaterial->media_id) || strtotime($findMaterial->expire_time) <= time())) {
            //素材本地文件
            $localFileInfo = (new SysFileService())->getLocalFileInfoByRemoteUrl($findMaterial->view_url);
            //重新上传临时素材
            $apiRs = $app->media->uploadVideo($localFileInfo['local_file_path']);
            //检查微信接口错误
            try {
                WxErrorService::checkApiResponse($apiRs);
                $findMaterial->media_id = $apiRs['media_id'] ?? '';
                $findMaterial->wx_view_url = $apiRs['url'] ?? '';
                $findMaterial->expire_time = $apiRs['created_at'] + 86400 * 3;
            } catch (\Exception $e) {
                $findMaterial->push_result = $e->getMessage();
            }
            $findMaterial->push_time = time();
            $findMaterial->save();
        }
        //永久素材
        if ($findMaterial->is_forever == 1 && empty($findMaterial->media_id)) {
            //素材本地文件
            $localFileInfo = (new SysFileService())->getLocalFileInfoByRemoteUrl($findMaterial->view_url);
            $apiRs = $app->material->uploadVideo($localFileInfo['local_file_path'], $findMaterial->title, $findMaterial->description);
            //检查微信接口错误
            try {
                WxErrorService::checkApiResponse($apiRs);
                $findMaterial->media_id = $apiRs['media_id'] ?? '';
                $findMaterial->wx_view_url = $apiRs['url'] ?? '';
                $findMaterial->expire_time = null;
            } catch (\Exception $e) {
                $findMaterial->push_result = $e->getMessage();
            }
            $findMaterial->push_time = time();
            $findMaterial->save();
        }
        return $findMaterial->media_id;
    }

    /**
     * 获取群发用的mediaId
     * @param $materialId
     * @param bool $reUpload
     * @return mixed
     * @throws \Exception
     */
    public function getMassMediaId($materialId, $reUpload = false)
    {
        $findMaterial = WxMaterial::findOrFail($materialId);
        $findMaterial->push_result = '';
        //上传到微信素材
        $app = \App\Services\EasyWechat::officialAccount();
        if (empty($findMaterial->mass_media_id)){
            //素材本地文件
            $localFileInfo = (new SysFileService())->getLocalFileInfoByRemoteUrl($findMaterial->view_url);
            //上传群发素材
            $apiRs = $app->media->uploadVideoForBroadcasting($localFileInfo['local_file_path']);
            WxErrorService::checkApiResponse($apiRs);
            $findMaterial->mass_media_id = $apiRs['media_id'] ?? '';
            $findMaterial->save();
        }
        return $findMaterial->media_id;
    }
    /**
     * 通过mediaId下载到本地
     * @param $mediaId
     * @param bool $isForever
     */
    public function downloadMediaId($mediaId, $isForever = true)
    {
        $findMaterial = WxMaterial::where('media_id', $mediaId)->select('material_id', 'title', 'description', 'file_id', 'view_url')->first();
        if (empty($findMaterial)) {
            $findMaterial = new WxMaterial;
            $findMaterial->media_id = $mediaId;
            //相对目录
            $savePath = 'upload' . DIRECTORY_SEPARATOR . date('Ymd');
            //首先下载到本地目录
            $app = EasyWechat::officialAccount();
            //
            if ($isForever) {//永久素材
                $apiRs = $app->material->get($mediaId);
                WxErrorService::checkApiResponse($apiRs);
                //拉取远程文件到本地
                $fileInfo = (new SysFileService())->getLocalFileInfoByRemoteUrl($apiRs['down_url'], 'mp4');
                $findMaterial->title = $apiRs['title'] ?? '';
                $findMaterial->description = $apiRs['description'] ?? '';
                $findMaterial->view_url = $fileInfo['view_url'];
                $findMaterial->wx_view_url = $apiRs['down_url'] ?? '';
                $findMaterial->file_id = $fileInfo['file_id'];
            } else {//临时素材
                $apiRs = $app->media->get($mediaId);
                WxErrorService::checkApiResponse($apiRs);
                //保存到本地
                //绝对路径
                $saveRealPath = \Storage::disk('local')->path($savePath);
                $newFileName = $apiRs->saveAs($saveRealPath);

                //$saveFileName = date("YmdHis") . uniqid();
                $fileExt = pathinfo($newFileName, PATHINFO_EXTENSION);
                $fileExt || $fileExt = 'mp4';
                $fileInfo = [
                    'disk_name' => 'sfy',
                    'origin_name' => 'thumb.' . $fileExt,//原始文件名
                    'file_ext' => $fileExt,//扩展名
                    'file_size' => 0,//文件大小
                    'file_type' => 'video',//文件类别
                    'new_name' => $newFileName,
                ];
                $fileInfo['file_path'] = $savePath . DIRECTORY_SEPARATOR . $newFileName;
                //文件真实路径
                $disk = \Storage::disk($fileInfo['disk_name']);
                $disk->put($fileInfo['file_path'], \File::get($saveRealPath . '.' . $newFileName));
                //文件大小
                $uploadInfo = (new SysFileService())->uploadFile($fileInfo['file_path'], $fileInfo['origin_name']);
                $fileInfo['view_url'] = $uploadInfo['url'];
                $fileInfo['file_size'] = $uploadInfo['size'];
                $sysFile = (new SysFileService())->saveFileInfo($fileInfo);

                $findMaterial->title = '微信端语音素材';
                $findMaterial->description = '微信端语音素材';
                $findMaterial->file_id = $sysFile->file_id;
                $findMaterial->view_url = $fileInfo['view_url'];
            }
            //保存到素材表
            $findMaterial->cat_id = 0;
            $findMaterial->type = 'video';
            $findMaterial->preview_data = [
                'title' => $findMaterial->title,
                'view_url' => $findMaterial->view_url = $fileInfo['view_url'],
            ];
            $findMaterial->is_forever = (int)$isForever;
            $findMaterial->save();
        }
        return $findMaterial;
    }

    /**
     * 同步线上数据到本地数据
     */
    public function sync()
    {
        $pageOffset = 0;
        $pageSize = 20;
        $total = 0;
        $itemPageCount = 0;//当前总数
        $itemTotalCount = 0;//该类别总数
        $app = EasyWechat::officialAccount();
        do {
            $list = $app->material->list('video', $pageOffset, $pageSize);
            WxErrorService::checkApiResponse($list);
            if (!empty($list['item'])) {
                foreach ($list['item'] as $v) {
                    try{
                        //语音不提供语音地址，需要通过mediaId保存到本地
                        $findMaterial = $this->downloadMediaId($v['media_id']);
                        $findMaterial->title = $v['name'] ?? '';
                        $findMaterial->save();
                        //语音无法像图片那样保存到本地
                        //$this->syncSave($v);
                    }catch (\Exception $e){
                        \Log::error('视频素材拉取失败：'.$e->getMessage(), $v);
                    }
                }
            }
            $itemPageCount = $list['item_count'] ?? 0;
            $itemTotalCount = $list['total_count'] ?? 0;
            $pageOffset += $itemPageCount;
            $total += $itemPageCount;
        } while ($itemPageCount == $pageSize && $total < $itemTotalCount);
        return true;
    }
    /**
     * 同步视频数据处理
     * @param $data
     * @return array
     * @throws \Exception
     */
    private function syncSave($data)
    {
        \DB::beginTransaction();
        try {
            if (empty($data['media_id'])) {
                throw new \Exception('空的素材ID');
            }
            if (empty($data['name'])) {
                throw new \Exception('素材名称不能为空');
            }
            if (empty($data['url'])) {
                throw new \Exception('视频访问地址为空');
            }
            $findMaterial = WxMaterial::where('media_id', $data['media_id'])->select('material_id', 'title', 'description', 'file_id', 'view_url')->first();
            if (empty($findMaterial)) {
                $findMaterial = new WxMaterial;
                //保存远程文件到本地
                $localFileInfo = (new SysFileService())->saveRemoteFile($data['url']);
                $fileInfo = [
                    'disk_name' => 'sfy',
                    'file_type' => 'video',
                    'file_ext' => $localFileInfo['file_ext'],
                    'origin_name' => $data['name'],
                    'new_name' => $localFileInfo['new_name'],
                    'file_path' => $localFileInfo['file_path'],
                ];
                //获取文件绝对路径
                $fileRealPath = \Storage::disk('local')->path($fileInfo['file_path']);
                $disk = \Storage::disk($fileInfo['disk_name']);
                $disk->put($fileInfo['file_path'], \File::get($fileRealPath));
                //文件大小
                $uploadInfo = (new SysFileService())->uploadFile($fileInfo['file_path'], $fileInfo['origin_name']);
                $fileInfo['view_url'] = $uploadInfo['url'];
                $fileInfo['file_size'] = $uploadInfo['size'];
                //保存文件数据
                $sysFile = (new SysFileService())->saveFileInfo($fileInfo);

                //微信端主表保存
                $findMaterial->cat_id = 0;
                $findMaterial->type = 'image';

                $findMaterial->title = '微信端素材-' . pathinfo($data['name'], PATHINFO_FILENAME);
                $findMaterial->media_id = $data['media_id'];
                $findMaterial->view_url = $fileInfo['view_url'] ?? '';
                $findMaterial->preview_data = [
                    'title' => $findMaterial->title,
                    'view_url' => $findMaterial->view_url,
                ];
                $findMaterial->file_id = $sysFile->file_id;
                $findMaterial->wx_view_url = $data['url'];
                $findMaterial->is_forever = 1;
                $findMaterial->push_time = $data['update_time'] ?? time();
                $findMaterial->save();
            }
            \DB::commit();
        } catch (\Exception $e) {
            \DB::rollBack();
            \Log::error($e->getMessage(), ['data' => $data]);
            throw new \Exception($e->getMessage());
        }

        return $findMaterial->toArray();
    }
}